package com.example.crawler.youtube.model.third;


import org.apache.commons.collections4.MapUtils;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Map;
import java.util.Set;

/**
 * @author YDF
 * @date 2019/12/26
 */
public class HttpUrlConnectionUtil {

    private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36";

    /**
     * 连接/读 超时时长。单位ms
     */
    private static int HTTP_CONNECTION_TIMEOUT = 30 * 1000;

    /**
     * 使用GET方法读取http中的数据
     *
     * @param urlAddress url地址
     * @return 请求的响应数据
     */
    public static String get(String urlAddress) {
        try {
            trustAllHttpsCertificates();
            HttpsURLConnection.setDefaultHostnameVerifier((urlHostName, session) -> true);
        } catch (Exception e) {
        }
        try {
            // 创建URL对象
            URL url = new URL(urlAddress);
            // 打开连接 获取连接对象
            URLConnection conn = url.openConnection();
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("Accept-Charset", "UTF-8");
            conn.setRequestProperty("user-agent", USER_AGENT);
            // 创建一个可变字符串对象，用来装载缓冲区对象的数据，使用字符串追加的方式，将响应的所有数据都保存在该对象中
            StringBuilder stringBuilder = new StringBuilder();
            try (
                    // 从连接对象中获取网络连接中的输入字节流对象
                    InputStream inputStream = conn.getInputStream();
                    // 将输入字节流包装成输入字符流对象,并进行字符编码
                    InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
                    // 创建一个输入缓冲区对象，将字符流对象传入
                    BufferedReader bufferedReader = new BufferedReader(inputStreamReader)
            ) {

                // 定义一个字符串变量，用来接收输入缓冲区中的每一行字符串数据
                String line;
                // 使用循环逐行读取输入缓冲区的数据，每次循环读入一行字符串数据赋值给line字符串变量，直到读取的行为空时标识内容读取结束循环
                while ((line = bufferedReader.readLine()) != null) {
                    // 将从输入缓冲区读取到的数据追加到可变字符对象中
                    stringBuilder.append(line);
                }
            }
            // 将可变字符串转换成String对象返回
            return stringBuilder.toString();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url   发送请求的 URL
     * @param param 请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
     * @return 所代表远程资源的响应结果
     */
    public static String post(String url, String param, Map<String, String> header) {
//        try {
//            trustAllHttpsCertificates();
//            HttpsURLConnection.setDefaultHostnameVerifier((urlHostName, session) -> true);
//        } catch (Exception e) {
//        }
        StringBuilder builder = new StringBuilder();
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // Post 请求不能使用缓存
            conn.setUseCaches(false);
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("Accept-Charset", "UTF-8");
            conn.setRequestProperty("user-agent", USER_AGENT);
            if (MapUtils.isNotEmpty(header)) {
                Set<Map.Entry<String, String>> entries = header.entrySet();
                for (Map.Entry<String, String> entry : entries) {
                    conn.setRequestProperty(entry.getKey(), entry.getValue());
                }
            }
            // 发送POST请求必须设置如下两行
            conn.setConnectTimeout(HTTP_CONNECTION_TIMEOUT);
            conn.setReadTimeout(HTTP_CONNECTION_TIMEOUT);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            try (PrintWriter out = new PrintWriter(conn.getOutputStream())) {
                // 发送请求参数
                out.print(param);
                // flush输出流的缓冲
                out.flush();
                // 定义BufferedReader输入流来读取URL的响应
                try (BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"))) {
                    String line;
                    while ((line = in.readLine()) != null) {
                        builder.append(line);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return builder.toString();
    }

    private static void trustAllHttpsCertificates() throws NoSuchAlgorithmException, KeyManagementException {
        TrustManager[] trustAllCerts = new TrustManager[1];
        trustAllCerts[0] = new TrustAllManager();
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, null);
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    }

    private static class TrustAllManager implements X509TrustManager {
        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        @Override
        public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
        }

        @Override
        public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
        }
    }
}
